#!/bin/bash

# Mall-Admin 健康检查脚本
# 用于容器启动和运行状态检查

set -e

# 配置参数
HOST=${HEALTH_CHECK_HOST:-localhost}
PORT=${SERVER_PORT:-8080}
TIMEOUT=${HEALTH_CHECK_TIMEOUT:-10}
MAX_RETRIES=${HEALTH_CHECK_MAX_RETRIES:-5}
RETRY_INTERVAL=${HEALTH_CHECK_RETRY_INTERVAL:-5}

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# 检查HTTP端点
check_http_endpoint() {
    local url=$1
    local description=$2
    
    log "检查 $description: $url"
    
    if curl -f -s --connect-timeout $TIMEOUT "$url" > /dev/null 2>&1; then
        log "✓ $description 检查通过"
        return 0
    else
        log "✗ $description 检查失败"
        return 1
    fi
}

# 检查TCP端口
check_tcp_port() {
    local host=$1
    local port=$2
    local description=$3
    
    log "检查 $description TCP连接: $host:$port"
    
    if timeout $TIMEOUT bash -c "</dev/tcp/$host/$port" 2>/dev/null; then
        log "✓ $description TCP连接正常"
        return 0
    else
        log "✗ $description TCP连接失败"
        return 1
    fi
}

# 主健康检查函数
main_health_check() {
    local retry_count=0
    local all_checks_passed=false
    
    while [ $retry_count -lt $MAX_RETRIES ] && [ "$all_checks_passed" = false ]; do
        log "开始第 $((retry_count + 1)) 次健康检查..."
        
        local checks_passed=0
        local total_checks=0
        
        # 检查应用端口
        total_checks=$((total_checks + 1))
        if check_tcp_port "$HOST" "$PORT" "应用端口"; then
            checks_passed=$((checks_passed + 1))
        fi
        
        # 检查基础健康端点
        total_checks=$((total_checks + 1))
        if check_http_endpoint "http://$HOST:$PORT/actuator/health" "Spring Boot Actuator健康检查"; then
            checks_passed=$((checks_passed + 1))
        fi
        
        # 检查存活状态
        total_checks=$((total_checks + 1))
        if check_http_endpoint "http://$HOST:$PORT/actuator/health/liveness" "应用存活状态"; then
            checks_passed=$((checks_passed + 1))
        fi
        
        # 检查就绪状态
        total_checks=$((total_checks + 1))
        if check_http_endpoint "http://$HOST:$PORT/actuator/health/readiness" "应用就绪状态"; then
            checks_passed=$((checks_passed + 1))
        fi
        
        # 检查自定义健康端点
        total_checks=$((total_checks + 1))
        if check_http_endpoint "http://$HOST:$PORT/health/status" "自定义健康检查"; then
            checks_passed=$((checks_passed + 1))
        fi
        
        # 判断检查结果
        if [ $checks_passed -eq $total_checks ]; then
            log "✓ 所有健康检查通过 ($checks_passed/$total_checks)"
            all_checks_passed=true
        else
            log "✗ 健康检查未完全通过 ($checks_passed/$total_checks)"
            retry_count=$((retry_count + 1))
            
            if [ $retry_count -lt $MAX_RETRIES ]; then
                log "等待 ${RETRY_INTERVAL}s 后重试..."
                sleep $RETRY_INTERVAL
            fi
        fi
    done
    
    if [ "$all_checks_passed" = true ]; then
        log "🎉 Mall-Admin 应用健康检查完全通过！"
        return 0
    else
        log "❌ Mall-Admin 应用健康检查失败，已达到最大重试次数"
        return 1
    fi
}

# 快速检查函数（用于容器健康检查）
quick_health_check() {
    # 优先检查存活状态
    if check_http_endpoint "http://$HOST:$PORT/actuator/health/liveness" "存活检查"; then
        return 0
    fi
    
    # 备用检查基础健康端点
    if check_http_endpoint "http://$HOST:$PORT/actuator/health" "基础健康检查"; then
        return 0
    fi
    
    # 最后检查自定义端点
    if check_http_endpoint "http://$HOST:$PORT/health/status" "自定义健康检查"; then
        return 0
    fi
    
    return 1
}

# 启动就绪检查
startup_readiness_check() {
    log "开始启动就绪检查..."
    
    # 等待应用端口可用
    local port_ready=false
    local wait_count=0
    local max_wait=30
    
    while [ "$port_ready" = false ] && [ $wait_count -lt $max_wait ]; do
        if check_tcp_port "$HOST" "$PORT" "应用端口"; then
            port_ready=true
        else
            wait_count=$((wait_count + 1))
            log "等待应用端口就绪... ($wait_count/$max_wait)"
            sleep 2
        fi
    done
    
    if [ "$port_ready" = false ]; then
        log "❌ 应用端口在 $((max_wait * 2))s 内未就绪"
        return 1
    fi
    
    # 执行完整健康检查
    main_health_check
}

# 根据参数执行不同类型的检查
case "${1:-main}" in
    "quick")
        log "执行快速健康检查..."
        quick_health_check
        ;;
    "startup")
        log "执行启动就绪检查..."
        startup_readiness_check
        ;;
    "main"|*)
        log "执行完整健康检查..."
        main_health_check
        ;;
esac

exit $?